﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Documents;
using AutoLoL.Entities;
using AutoLoL.Logic;
using AutoLoL.Logic.Game;
using AutoLoL.Logic.Parsers;
using AutoLoL.Logic.Utils;
using AutoLoL.Shared;
using Ionic.Zip;
using Ionic.Zlib;

namespace AutoLoL.Playground
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // Testing vars
            if (Environment.MachineName.Equals("DESKTOP"))
            {
                UserSettings.Instance.LolDirectory = @"D:\Games\Riot Games\League of Legends";
            }
            else if (Environment.MachineName.Equals("LAPTOP"))
            {
                UserSettings.Instance.LolDirectory = @"\\Desktop\D\Games\Riot Games\League of Legends";
            }
            else
            {
                UserSettings.Instance.LolDirectory = @"C:\Games\League of Legends";
            }

            new ForumWindow().Show();
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            InibinCompareWindow dialog = new InibinCompareWindow();
            dialog.CompareData(GetSummonerSpells());
            dialog.ShowDialog();
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            InibinCompareWindow dialog = new InibinCompareWindow();
            dialog.CompareData(GetItems().ToList());
            dialog.ShowDialog();
        }

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            InibinCompareWindow dialog = new InibinCompareWindow();
            dialog.CompareData(GetCharacters().ToList());
            dialog.ShowDialog();
        }

        private void button4_Click(object sender, RoutedEventArgs e)
        {
            new RafBrowser().ShowDialog();
        }

        private void button5_Click(object sender, RoutedEventArgs e)
        {
            InibinCompareWindow dialog = new InibinCompareWindow();
            dialog.CompareData(GetCharacters("rumble").ToList());
            dialog.ShowDialog();
        }

        private List<InibinData> GetCharacters(string filter = null)
        {
            string pakPath = System.IO.Path.Combine(UserSettings.Instance.LolDirectory, "Game", "HeroPak_client.zip");

            if (!Directory.Exists(Constants.TEMP_DIRECTORY))
            {
                Directory.CreateDirectory(Constants.TEMP_DIRECTORY);
            }

            using (ZipFile zipFile = new ZipFile(pakPath))
            {
                // Get all character inibin files
                ZipEntry[] characterEntries = zipFile.Entries.Where(c =>
                    // data\characters directory
                    c.FileName.ReplaceForwardWithBackwardSlash().ToLower().StartsWith("data\\characters\\")
                        // only inibin files
                    && c.FileName.ToLower().EndsWith(".inibin")
                        // 3 directories and 1 file
                    && c.FileName.ReplaceForwardWithBackwardSlash().Split('\\').Length == 4).ToArray();

                if (!string.IsNullOrEmpty(filter))
                {
                    characterEntries = characterEntries.Where(c => c.FileName.ToLower().Contains(filter.ToLower())).ToArray();
                }

                List<InibinData> datas = new List<InibinData>();

                foreach (ZipEntry zipEntry in characterEntries)
                {
                    string absoluteInibinPath = ExtractZipEntry(zipEntry, Constants.TEMP_DIRECTORY);
                    Dictionary<uint, InibinEntry> inibinData = InibinParser.ParseFile(absoluteInibinPath);
                    TryDeleteFile(absoluteInibinPath);

                    InibinData data = new InibinData();
                    foreach (uint key in inibinData.Keys)
                    {
                        string v = inibinData[key].ToString();

                        if (key == (uint)InibinKeys.Character.FCK_NAME)
                        {
                            string fckName = inibinData[key].GetString();
                            v = FontConfigParser.Instance.GetValue(fckName);
                        }

                        data[key] = v;
                    }

                    datas.Add(data);
                }

                return datas;
            }
        }

        private List<InibinData> GetItems()
        {
            string pakPath = System.IO.Path.Combine(UserSettings.Instance.LolDirectory, "Game", "HeroPak_client.zip");

            if (!Directory.Exists(Constants.TEMP_DIRECTORY))
            {
                Directory.CreateDirectory(Constants.TEMP_DIRECTORY);
            }

            using (ZipFile zipFile = new ZipFile(pakPath))
            {
                // Get all item inibin files
                ZipEntry[] itemEntries = zipFile.Entries.Where(c =>
                    c.FileName.ToLower().ReplaceForwardWithBackwardSlash().StartsWith("data\\items\\")
                    && c.FileName.ReplaceForwardWithBackwardSlash().ToLower().EndsWith(".inibin")).ToArray();

                List<InibinData> datas = new List<InibinData>();

                foreach (ZipEntry zipEntry in itemEntries)
                {
                    string absoluteInibinPath = ExtractZipEntry(zipEntry, Constants.TEMP_DIRECTORY);
                    Dictionary<uint, InibinEntry> inibinData = InibinParser.ParseFile(absoluteInibinPath);
                    TryDeleteFile(absoluteInibinPath);

                    // Only parse valid items
                    if (inibinData.ContainsKey((uint)InibinKeys.Item.IS_VALID) && inibinData[(uint)InibinKeys.Item.IS_VALID].GetBit())
                    {
                        InibinData data = new InibinData();
                        foreach (uint key in inibinData.Keys)
                        {
                            string v = inibinData[key].ToString(); ;

                            if (key == (uint)InibinKeys.Item.FCK_NAME)
                            {
                                string fckName = inibinData[key].GetString();
                                v = FontConfigParser.Instance.GetValue(fckName);
                            }

                            data[key] = v;
                        }

                        datas.Add(data);
                    }
                }

                return datas;
            }
        }

        private List<InibinData> GetSummonerSpells()
        {
            string pakPath = System.IO.Path.Combine(UserSettings.Instance.LolDirectory, "Game", "HeroPak_client.zip");

            if (!Directory.Exists(Constants.TEMP_DIRECTORY))
            {
                Directory.CreateDirectory(Constants.TEMP_DIRECTORY);
            }

            using (ZipFile zipFile = new ZipFile(pakPath))
            {
                // Get all summoner spell inibin files
                ZipEntry[] summonerSpellEntries = zipFile.Entries.Where(c =>
                    // data\spells directory
                    c.FileName.ReplaceForwardWithBackwardSlash().ToLower().StartsWith("data\\spells\\summoner")
                        // only inibin files
                    && c.FileName.ToLower().EndsWith(".inibin")
                        // 2 directories and 1 file
                    && c.FileName.ReplaceForwardWithBackwardSlash().Split('\\').Length == 3).ToArray();

                List<InibinData> datas = new List<InibinData>();

                foreach (ZipEntry zipEntry in summonerSpellEntries)
                {
                    string[] inibinZipPathSections = zipEntry.FileName.ReplaceForwardWithBackwardSlash().Split('\\');

                    string absoluteInibinPath = ExtractZipEntry(zipEntry, Constants.TEMP_DIRECTORY);
                    Dictionary<uint, InibinEntry> inibinData = InibinParser.ParseFile(absoluteInibinPath);
                    TryDeleteFile(absoluteInibinPath);

                    InibinData data = new InibinData();
                    foreach (uint key in inibinData.Keys)
                    {
                        string v = inibinData[key].ToString(); ;

                        if (key == (uint)InibinKeys.SummonerSpell.FCK_NAME)
                        {
                            string fckName = inibinData[key].GetString();
                            v = FontConfigParser.Instance.GetValue(fckName);
                        }

                        data[key] = v;
                    }

                    datas.Add(data);
                }

                return datas;
            }
        }

        private string ExtractZipEntry(ZipEntry entry, string directory)
        {
            entry.Extract(directory, ExtractExistingFileAction.OverwriteSilently);
            string[] pathSections = entry.FileName.ReplaceForwardWithBackwardSlash().Split('\\');
            string relativePath = System.IO.Path.Combine(pathSections);
            string absolutePath = System.IO.Path.Combine(directory, relativePath);
            return absolutePath;
        }

        private void TryDeleteFile(string filePath)
        {
            try { File.Delete(filePath); }
            catch { if (Debugger.IsAttached) throw; }
        }

        private void button5_Click_1(object sender, RoutedEventArgs e)
        {
            new PixelChecker().ShowDialog();
        }

        private void gameMemory_click(object sender, RoutedEventArgs e)
        {
            new GameMemoryWindow().ShowDialog();
        }
    }
}
